/*******************************************************************************
*
* Copyright (C) 2013 - 2015, Jeffery Jiang, <china_jeffery@163.com>.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
*
* Expect bugs
*
* Please use and enjoy. Please let me know of any bugs/mods/improvements
* that you have found/implemented and I will fix/incorporate them into this
* file.
*
*******************************************************************************/

#ifndef __PIPE_WIN_DF454D_H__
#define __PIPE_WIN_DF454D_H__

#include "types.h"
#include "IoCompletionPort.h"
#include "libipc.h"

enum {
    OP_CONNECT,
    OP_READ,
    OP_WRITE,
    OP_DISCONNECT
};

const DWORD kBufSize = 4096;
const int kIPCMaxConcurrent = 20;

struct PipeOverlapped {
    OVERLAPPED ol;
    int iOpCode;
    HANDLE hPipe;
    LPVOID pvBuff;
    DWORD dwBuffMaxSize;
    DWORD dwDataSize;

    PipeOverlapped() {
        memset(&ol, 0, sizeof(ol));
        hPipe = NULL;
        dwDataSize = 0;
        dwBuffMaxSize = kBufSize;
        pvBuff = malloc(kBufSize);

        if(NULL == pvBuff)
            throw(1);
    }

    ~PipeOverlapped() {
        SAFE_FREE(pvBuff);
    }
};


class WinPipe {
  public:
    WinPipe();
    ~WinPipe();

    BOOL StartListen(LPCTSTR szIPCName, PFN_LISTENING_CALLBACK pfnCallback);
    void StopListen(void);
    DWORD GetIPCName(TCHAR *szName, DWORD dwMaxSize);
    BOOL SetBufferSize(DWORD dwSize);
    BOOL SetMaxConcurrent(int concurrent);

  private:
    BOOL ReadPipe(PipeOverlapped *pPipeOL);
    BOOL Reconnect(PipeOverlapped *pPipeOL);
  private:
    BOOL m_bListening;
    CIOCP m_ICOP;
    TCHAR m_szIPCName[MAX_PATH + 1];
    PipeOverlapped *m_PipeOLs;
    HANDLE *m_pWorkThreads;
    int m_iWorkThreadNum;
    HANDLE m_hVirtualMainThread;
    int m_iMaxConcurrent;
    DWORD m_dwBufferSize;

    PFN_LISTENING_CALLBACK m_pfnListenCallback;

    friend unsigned int __stdcall WorkThread(void *param);
    friend unsigned int __stdcall VirtualMainThread(void *param);
};


#endif